package com.example.memegenerator.service;

import org.springframework.stereotype.Service;

import javax.imageio.IIOImage;
import javax.imageio.ImageIO;
import javax.imageio.ImageTypeSpecifier;
import javax.imageio.ImageWriteParam;
import javax.imageio.ImageWriter;
import javax.imageio.metadata.IIOMetadata;
import javax.imageio.metadata.IIOMetadataNode;
import javax.imageio.stream.ImageOutputStream;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.Iterator;
import java.util.List;

@Service
public class GifService {

    /**
     * 创建GIF动画
     * 
     * @param frames 帧列表
     * @param delayTime 帧之间的延迟时间（毫秒）
     * @return GIF数据的字节数组
     * @throws IOException 如果创建GIF时发生IO错误
     */
    public byte[] createGif(List<BufferedImage> frames, int delayTime) throws IOException {
        if (frames == null || frames.isEmpty()) {
            throw new IllegalArgumentException("帧列表不能为空");
        }

        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        
        // 获取GIF ImageWriter
        Iterator<ImageWriter> writers = ImageIO.getImageWritersByFormatName("gif");
        if (!writers.hasNext()) {
            throw new IOException("没有可用的GIF图像写入器");
        }
        
        ImageWriter writer = writers.next();
        ImageOutputStream imageOutputStream = ImageIO.createImageOutputStream(outputStream);
        writer.setOutput(imageOutputStream);
        
        // 写入GIF文件的基本属性
        writer.prepareWriteSequence(null);
        
        // 添加每一帧
        for (BufferedImage frame : frames) {
            IIOMetadata metadata = getFrameMetadata(writer, frame, delayTime);
            IIOImage iioImage = new IIOImage(frame, null, metadata);
            writer.writeToSequence(iioImage, null);
        }
        
        // 完成写入
        writer.endWriteSequence();
        imageOutputStream.close();
        writer.dispose();
        
        return outputStream.toByteArray();
    }
    
    /**
     * 设置单个帧的元数据，主要是延迟时间
     */
    private IIOMetadata getFrameMetadata(ImageWriter writer, BufferedImage image, int delayTime) throws IOException {
        // 获取默认的元数据
        ImageWriteParam iwp = writer.getDefaultWriteParam();
        IIOMetadata metadata = writer.getDefaultImageMetadata(new ImageTypeSpecifier(image), iwp);
        
        // 设置延迟时间（以0.01秒为单位）
        String metaFormatName = metadata.getNativeMetadataFormatName();
        IIOMetadataNode root = (IIOMetadataNode) metadata.getAsTree(metaFormatName);
        
        IIOMetadataNode graphicsControlExtensionNode = getNode(root, "GraphicControlExtension");
        graphicsControlExtensionNode.setAttribute("disposalMethod", "none");
        graphicsControlExtensionNode.setAttribute("userInputFlag", "FALSE");
        graphicsControlExtensionNode.setAttribute("transparentColorFlag", "FALSE");
        graphicsControlExtensionNode.setAttribute("delayTime", Integer.toString(delayTime / 10)); // 转换为0.01秒
        graphicsControlExtensionNode.setAttribute("transparentColorIndex", "0");
        
        IIOMetadataNode commentsNode = getNode(root, "CommentExtensions");
        commentsNode.setAttribute("CommentExtension", "Created by Meme Generator");
        
        IIOMetadataNode appExtensionsNode = getNode(root, "ApplicationExtensions");
        IIOMetadataNode child = new IIOMetadataNode("ApplicationExtension");
        child.setAttribute("applicationID", "NETSCAPE");
        child.setAttribute("authenticationCode", "2.0");
        
        // 设置循环
        byte[] loopBytes = new byte[]{1, 0, 0};
        child.setUserObject(loopBytes);
        appExtensionsNode.appendChild(child);
        
        metadata.setFromTree(metaFormatName, root);
        
        return metadata;
    }
    
    /**
     * 获取或创建元数据节点
     */
    private IIOMetadataNode getNode(IIOMetadataNode rootNode, String nodeName) {
        for (int i = 0; i < rootNode.getLength(); i++) {
            if (rootNode.item(i).getNodeName().equalsIgnoreCase(nodeName)) {
                return (IIOMetadataNode) rootNode.item(i);
            }
        }
        
        IIOMetadataNode node = new IIOMetadataNode(nodeName);
        rootNode.appendChild(node);
        return node;
    }
} 